﻿#ifndef AGVHARDWARE_H
#define AGVHARDWARE_H

class Maindeal;
#include "battery_ropeencoder_can.h"
#include "can.h"
#include "charging/chargingmodel.h"
#include "io.h"
#include "maindeal.h"
#include "motor/forklift/forkliftdrive.h"
#include "param.h"
#include "qnode.hpp"
#include "qrcode.h"
#include "utility.h"
#include <QBitArray>
#include <QDebug>
#include <QMap>
#include <QMetaEnum>
#include <QObject>
#include <QThread>

/********  叉车地盘驱动                          ********/
//#define ARESMOTECFORKDRIVE  // 选择叉车地盘驱动  柯蒂斯控制器 + ARES伺服舵轮转角电机
//#define DMKEMOTECFORKDRIVE  // 选择叉车地盘驱动  柯蒂斯控制器 + DMAKE伺服舵轮转角电机
#define BUKEKEDISHIFORKDRIVE  // 选择叉车地盘驱动  柯蒂斯控制器 + 步科伺服舵轮转角电机

#ifdef ARESMOTECFORKDRIVE
#include "motor/forklift/aresmotecdrive.h"
#endif

#ifdef DMKEMOTECFORKDRIVE
#include "motor/forklift/dmakemotecdrive.h"
#endif

#ifdef BUKEKEDISHIFORKDRIVE
#include "motor/forklift/bukekedishidrive.h"
#endif

/********  叉车地盘驱动                          ********/

/********  充电桩IO驱动                          ********/
//#define PILE      // pile
#define ZHONGSHENG  // 中盛科技

#ifdef PILE
#include "charging/charging_pile_io.h"
#endif

#ifdef ZHONGSHENG
#include "charging/charging_zhongsheng_io.h"
#endif
/********  充电桩IO驱动                          ********/

class Agvhardware : public QObject {
    Q_OBJECT
public:
    explicit Agvhardware( int argc, char** argv, Maindeal* maindeal, QObject* parent = nullptr );

    ~Agvhardware();

    //货叉升降位置动作
    enum ForkliftState {
        STOP = 0,  //停止
        RAISE,
        FALL,
    };

    //货叉获取位置及状态 未知  上升中 下降中 低低位 低位 高位 高高位
    enum ForkPosState {
        FORK_UNKNOWN = 0,  //未知位置
        FORK_RAISING,      //货叉上升中
        FORK_FALLING,      //货叉下降中
        FORK_BOTTOM,       //货叉下限位
        FORK_TOP,          //货叉上限位
        FORK_ORIGIN,       //货叉原点
    };

    // TEST 修改传输类型2：状态类型
    enum AgvState {
        // AGV行驶 收到行走指令就切换该状态
        AGV_RUNNING   = 1,   // AGV行驶 收到行走指令就切换该状态
        AGV_ARRIVE    = 2,   // AGV到站 每一个站点的到达和初始默认状态
        AGV_LIFT_STOP = 3,   // AGV升降暂停
        AGV_PRECHARGE = 4,   // AGV准备充电
        AGV_CHARGING  = 5,   // AGV充电
        AGV_TRAFFIC   = 6,   // AGV交管
        AGV_STOP      = 7,   // AGV停止
        AGV_OBSTACLE  = 8,   // AGV避障
        AGV_EMERGENCY = 9,   // AGV急停 发送异常情况切换（壁障异常和其他异常的区别，有停止，有自动恢复，状态切换有难度！）
        AGV_FORK      = 10,  // AGV升降
    };

    Q_ENUM( AgvState )

    //托盘货叉上状态 空 空托盘 托盘+货物
    enum GoodsState {
        EMPTY = 0,
        PALLET,
        PALLET_AND_GOODS,
    };

    bool isNeedAlarm();                                               //是否报警
    bool isHardwareError();                                           //硬件错误
    bool isNeedEmergencyStop();                                       //急停
    bool isObstacleSlowDown( bool isForward );                        //障碍物减速区
    bool isObstacleStop( bool isForward );                            //障碍物急停区
    bool isSlamObstacleStop( int T );                                 //是否允许传输导航障碍物急停区
    bool isLowPower() const;                                          //低电量
    bool isAgvArriveSignal();                                         // AGV到达信号
    bool isAlarm() const;                                             //报警
    bool isAllowForklift();                                           //是否允许传输
    bool isOnlyLeftObsStop();                                         //是否仅有左避障急停层触发
    bool isOnlyRightObsStop();                                        //是否仅有右避障急停层触发
    void buttonEvent();                                               //按钮事件
    void autoModeLed( bool sw );                                      //自动模式
    void lightControl();                                              //灯光控制
    void musicControl();                                              //音乐控制
    void abortHandler();                                              //崩溃事件处理
    void setChargeEnable( bool state );                               //设置充电使能
    void setAgvState( const AgvState& agvstate );                     // AGV状态
    void waitingCloseAgv();                                           //等待关闭AGV
    void setAlarm( bool isAlarm );                                    //设置报警
    void resetHardwareState();                                        //复位硬件状态
    void ChangeObs( int left, int right, int back, int slam_laser );  //切换OBS避障区域左 右 后 导航雷达
    void ScanSignal();                                                //扫描信号
    //  void EmergencyStopTranSmit();
    void         resetServoDriverAlarm();  //复位私服驱动报警
    GoodsState   getGoodsState();          //获取货物状态
    AgvState     getAgvState() const;      //获取AGV状态
    ForkPosState getForkPosState();        //获取货叉位置状态

    //    CAN* canModule() const;

    ForkliftDrive* canModule() const;

    IO*                      ioModule() const;
    ChargingModel*           chargingPileModule() const;
    Battery_Ropeencoder_can* Battery_Ropeencoder_canModule() const;

    // obs 加入左右避障开关
    void setL_R_obs_open( bool l, bool r );
    bool get_l_obs_open();
    bool get_r_obs_open();

    void stopCharge();   //停止充电
    void startCharge();  //开始充电

    //升降动作
    void setForkliftState( const ForkliftState& state );  //设定货叉动作
    void ForkliftHandle();                                //货叉升降处理

    void onAutoChange( bool isAuto );          //自动模式切换
    void onForkAutoChange( bool isForkAuto );  //叉车控制自动模式切换
private:
    QThread*                 thread_1                       = nullptr;  //线程1
    QThread*                 thread_2                       = nullptr;  //线程2
    Maindeal*                maindeal                       = nullptr;  //主处理指针
    CAN*                     can_module                     = nullptr;
    ForkliftDrive*           forklift_drive_module          = nullptr;
    IO*                      io_module                      = nullptr;
    ChargingModel*           charging_module                = nullptr;
    Battery_Ropeencoder_can* Battery_Ropeencoder_can_Module = nullptr;

    bool   chargingFinish = false;  //充电桩通讯控制完成
    int    argc;
    char** argv;
    bool   is_transmit_enable = false;                   //传输功能开关
    bool   is_low_power       = false;                   //电池是否低压
    bool   left_obs_flag = true, right_obs_flag = true;  // DPDATE 221028 左右避障的开关
                                                         // TransmitDelay upper_left_delay, upper_right_delay, lower_left_delay, lower_right_delay;
    AgvState agv_state = AGV_STOP;                       // AGV的状态，大部分逻辑的判断都基于这个状态，需要谨慎设置。
    AgvState last_agv_state;                             //上一次AGV的状态，记录该状态是为了暂停时候恢复状态使用。
    bool     is_alarm_ = false;                          //报警异常判断
    //升降
    ForkliftState fork_lift_action = STOP;

    GoodsState goods_state = EMPTY;

signals:
    void sigSendTips( const QString& );
    void sigStartButtonHit();

public slots:
    void sltchargingFinish();
    void sltAgvHardwareInit();
    void sltLoseConnect( const QString& message );
    //  void sltQrcodRecvieNaviParam();
    void sltRFIDRecvieNaviParam( const int& rfidId );
    void slt50msTimer();
    void slt100msTimer();
    void slt500msTimer();
    void slt1000msTimer();
};

#endif  // AGV_H
